package com.amon.canary;

import android.util.Log;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class IOCanary {
    static {
        System.loadLibrary("canary");
        hook();
    }

    private static native void hook();

    private static String getJavaStack() {
        StackTraceElement[] stackTraceElements = new Throwable().getStackTrace();
        StringBuilder sb = new StringBuilder();
        for (StackTraceElement stackTraceElement : stackTraceElements) {
            if (stackTraceElement.toString().contains(IOCanary.class.getName())) {
                continue;
            }
            sb.append(stackTraceElement.toString()).append("\r\n");
        }
        Log.i("TAG", sb.toString());
        return sb.toString();
    }

    public static void hookCloseGuardReport() {
//        try {
//            Class<?> closeGuardCls = Class.forName("dalvik.system.CloseGuard");
//            Method getReporterMethod = closeGuardCls.getDeclaredMethod("getReporter", null);
//            getReporterMethod.setAccessible(true);
//            Object reporter = getReporterMethod.invoke(null);
//
//            Class<?> reportInterfaceClass = Class.forName("dalvik.system.CloseGuard$Reporter");
//            Object reporterProxy = Proxy.newProxyInstance(IOCanary.class.getClassLoader(),
//                    new Class<?>[]{reportInterfaceClass},
//                    new IoCloseInvocationHandler(reporter));
//            Method setReporterMethod = closeGuardCls.getDeclaredMethod("setReporter", reporter.getClass().getSuperclass());
//            setReporterMethod.setAccessible(true);
//            setReporterMethod.invoke(null, reporterProxy);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
    }

    private static class IoCloseInvocationHandler implements InvocationHandler {
        private final Object originalReporter;

        public IoCloseInvocationHandler(Object reporter) {
            this.originalReporter = reporter;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if ("report".equals(method.getName())) {
                Throwable throwable = (Throwable) args[1];
                throwable.printStackTrace();
            }
            return method.invoke(originalReporter, args);
        }
    }
}
